import torch
import numpy as np

# 1. torch.tensor() 方法
# 从 Python 列表创建张量
# 这里创建了一个2x3的二维列表
py_list = [[1,2,3],[4,5,6]]
# 使用torch.tensor()将Python列表转换为PyTorch张量
t1 = torch.tensor(py_list)
print(f"From list:\n {t1}")  # 打印从列表创建的张量

# 从 NumPy 数组创建张量 (会复制数据)
# 首先将Python列表转换为NumPy数组
np_array = np.array(py_list)
# 使用torch.tensor()将NumPy数组转换为PyTorch张量，并指定数据类型为float32
# 注意：这种方式会复制数据，即创建数据的副本
t2 = torch.tensor(np_array,dtype=torch.float32)
print(f"From NumPy array (copied):\n {t2}\n")

# 修改原始 NumPy 数组，t2 不会改变
# 这证明torch.tensor()是复制数据而非共享内存
np_array[0,0] = 99  # 修改NumPy数组的第一个元素
print(f"Original NumPy array modified:\n {np_array}\n")  # 显示修改后的NumPy数组
print(f"Tensor t2 remains unchanged:\n {t2}\n")  # 显示张量t2保持不变


# 2. torch.from_numpy() 方法
# 专门用于从 NumPy 数组创建 Tensor。它非常高效，因为它与 NumPy 数组共享内存。
np_array_shared = np.array([[10, 20], [30, 40]])
# 使用from_numpy创建张量，与NumPy数组共享内存
t3 = torch.from_numpy(np_array_shared)
print(f"From NumPy array (shared memory):\n {t3}\n")

# 修改Tensor，NumPy数组也会改变，因为它们共享内存
t3[0,0] = 999  # 修改张量t3的第一个元素
print(f"Tensor t3 modified:\n {t3}\n")  # 显示修改后的张量
print(f"Original NumPy array is also changed:\n {np_array_shared}\n")  # NumPy数组也随之改变


# 3. torch.as_tensor() 方法
# 如果源数据是 NumPy 数组，它的行为类似于 torch.from_numpy()（共享内存）。
# 如果源数据是 Python 列表，它的行为类似于 torch.tensor()（复制数据）。
np_array_as = np.array([[1., 2.], [3., 4.]])
t4 = torch.as_tensor(np_array_as) #共享内存，与NumPy数组共享底层数据
t4[0,0] = -1
print(f"Tensor from as_tensor:\n {t4}\n")
print(f"Original NumPy array for as_tensor:\n {np_array_as}\n")


# 行为类似 tensor
py_list_as = [1,2,3]
# 复制数据
t5 = torch.as_tensor(py_list_as)
py_list_as[0] = -1
print(f"Tensor from list with as_tensor:\n {t5}")
print(f"Original list for as_tensor:\n {py_list_as}")
